package com.ruoyi.worker.domain.workAttendance;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.ImmutableMap;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.worker.constant.Constant;
import com.ruoyi.worker.domain.MonthlyAttendanceIni;
import com.ruoyi.worker.domain.TermAttendanceGroup;
import com.ruoyi.worker.domain.TermAttendanceRules;
import lombok.Data;
import lombok.ToString;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName AttendanceInformation
 * @Description 考勤子表实体对象
 * @Author leizhang
 * Date 2021/11/16 9:53 下午
 * @Version 1.0
 **/
@Data
@ToString
public class AttendanceDailyRecord extends TermAttendanceGroup {
    /**
     * 姓名
     **/
    @Excel(name = "员工姓名", width = 20)
    String staffName;

    /**
     * 身份证
     **/
    @Excel(name = "身份证号", width = 30)
    String idCard;

    /**
     * 排班时间
     **/
    @Excel(name = "考勤时间", width = 20)
    String workTime;

    /**
     * 岗位名称
     **/
    @Excel(name = "岗位", width = 20)
    String postName;

    /**
     * 班组名称
     **/
    @Excel(name = "班组名称", width = 20)
    String deptName;

    /**
     * 班组id
     **/
    @Excel(name = "班组id", width = 20)
    String deptId;

    @Excel(name = "班次id", width = 20)
    public Long shiftId;

    @Excel(name = "班次名称", width = 20)
    public String shiftName;

    /**
     * 考勤异常,请假,旷工，工伤等 未打卡记录 3-正常 1-休息 2-旷工 7-异常
     **/
    @Excel(name = "出勤", replace = {"正常_3", "休息_1", "旷工_2", "异常_7"}, width = 20, addressList = true)
    int abnormalAttendance = 3;

    /**
     * 汇总主表id
     **/
    String sumRecordId;

    /**
     * 岗位
     **/
    String stationName;

    /**
     * 组别名称
     **/
    String groupName;

    /**
     * 组别id
     **/
    int groupId;

    /**
     * 工作类型 1-工作类型 2-非工作类型(休息)
     **/
    int attendanceType;

    /**
     * 应该打卡次数,应打卡次数 等于考勤考勤规则中的打卡次数
     **/
    @Excel(name = "应打卡次数", width = 20)
    int needSign;

    /**
     * 正常打卡次数，应打卡次数 - 异常打卡次数
     **/
    @Excel(name = "正常打卡次数", width = 20, isColumnHidden = true)
    int normalSign;

    /**
     * 打卡异常， 异常次数 = 普通迟到 + 一般迟到 + 严重迟到 + 早退 + 旷工
     **/
    @Excel(name = "异常打卡次数", width = 20, isColumnHidden = true)
    int abnormalSign;

    /**
     * 普通迟到
     **/
    @Excel(name = "普通迟到", width = 20)
    int normallyLate;

    /**
     * 一般迟到
     **/
    @Excel(name = "一般迟到", width = 20)
    int usuallyLate;

    /**
     * 严重迟到
     **/
    @Excel(name = "严重迟到", width = 20)
    int severelyLate;

    /**
     * 早退
     **/
    @Excel(name = "早退", width = 20)
    int leaveEarly;

    /**
     * 旷工
     **/
    @Excel(name = "旷工", width = 20)
    int absenteeism;

    /**
     * 第一次打卡记录记过 1-正常 2-普通迟到 3-一般迟到 4- 严重迟到 5-早退 6-旷工 7-考勤异常(未打卡)
     **/
    @Excel(name = "早上上班", width = 30, replace = {"正常_1", "普通迟到_2", "一般迟到_3", "严重迟到_4", "早退_5", "旷工_6", "异常_7", "休息_8"}, addressList = true)
    Integer firstSignInResult = 1;
    @Excel(name = "早上上班打卡时间", width = 30)
    String firstSignInTime;
    //    @Excel(name = "第一次下班", width = 30, replace = {"正常_1", "普通迟到_2", "一般迟到_3", "严重迟到_4", "早退_5", "旷工_6", "异常_7", "休息_8"}, addressList = true)
    Integer firstSignOutResult = 1;
    @Excel(name = "中午上班", width = 30, replace = {"正常_1", "普通迟到_2", "一般迟到_3", "严重迟到_4", "早退_5", "旷工_6", "异常_7", "休息_8"}, addressList = true)
    Integer secondSignInResult = 1;
    @Excel(name = "中午上班打卡时间", width = 30)
    String secondSignInTime;
    //    @Excel(name = "第二次下班", width = 30, replace = {"正常_1", "普通迟到_2", "一般迟到_3", "严重迟到_4", "早退_5", "旷工_6", "异常_7", "休息_8"}, addressList = true)
    Integer secondSignOutResult = 1;
    @Excel(name = "下午上班", width = 30, replace = {"正常_1", "普通迟到_2", "一般迟到_3", "严重迟到_4", "早退_5", "旷工_6", "异常_7", "休息_8"}, addressList = true)
    Integer thirdSignInResult = 1;
    @Excel(name = "下午上班打卡时间", width = 30)
    String thirdSignInTime;
    @Excel(name = "下班", width = 30, replace = {"正常_1", "普通迟到_2", "一般迟到_3", "严重迟到_4", "早退_5", "旷工_6", "异常_7", "休息_8"}, addressList = true)
    Integer thirdSignOutResult = 1;
    @Excel(name = "下班打卡时间", width = 30)
    String thirdSignOutTime;
    //    @Excel(name = "第四次上班", width = 30, replace = {"正常_1", "普通迟到_2", "一般迟到_3", "严重迟到_4", "早退_5", "旷工_6", "异常_7", "休息_8"}, addressList = true)
    Integer forthSignInResult = 1;
    //    @Excel(name = "下班", width = 30, replace = {"正常_1", "普通迟到_2", "一般迟到_3", "严重迟到_4", "早退_5", "旷工_6", "异常_7", "休息_8"}, addressList = true)
    Integer forthSignOutResult = 1;


    //    @Excel(name = "第一次下班打卡时间", width = 30)
    String firstSignOutTime;

    //    @Excel(name = "第二次下班打卡时间", width = 30)
    String secondSignOutTime;


    //    @Excel(name = "第四次上班打卡时间", width = 30)
    String forthSignInTime;
    //    @Excel(name = "下班打卡时间", width = 30)
    String forthSignOutTime;


    /**
     * 考勤规则
     **/
    private TermAttendanceRules termAttendanceRules;

    /**
     * 考勤数据-上班打卡(已废除)
     **/
    @Deprecated
    private List<MonthlyAttendanceIni> monthlyAttendanceIniSignIn;

    /**
     * 考勤数据-下班打卡(已废除)
     **/
    @Deprecated
    private List<MonthlyAttendanceIni> monthlyAttendanceIniSignOut;

    /**
     * 通行记录
     **/
    private List<MonthlyAttendanceIni> attendanceRecords;
    /**
     * 数据类型 1-考勤上班打卡时间 2-考勤下班打卡时间
     **/
    private int dataType;

    /*
     每个班最早的上班时间
     */
    private String firstInTime;
    /*
    每个班最后的下班时间
     */
    private String lastOutTime;

    /**
     * 计算各个指标的结果
     **/
    public void calculateAttendanceResult(String baseDate) {
        if (attendanceType == 2) {
            //非工作日
            abnormalAttendance = 1;
            firstSignOutResult = secondSignOutResult = thirdSignOutResult = forthSignOutResult = 8;
            firstSignInResult = secondSignInResult = thirdSignInResult = forthSignInResult = 8;
            return;
        }
        //排班无通行记录
        if (null == attendanceRecords) {
            abnormalAttendance = 7;
            firstSignOutResult = secondSignOutResult = thirdSignOutResult = forthSignOutResult = 7;
            firstSignInResult = secondSignInResult = thirdSignInResult = forthSignInResult = 7;
            return;
        }
        //考勤数据判断：如果考勤数据为空，则判断异常(无打卡记录)
        boolean attendanceFlag = attendanceRecords.isEmpty();
        if (attendanceFlag) {
            abnormalAttendance = 7;
            firstSignOutResult = secondSignOutResult = thirdSignOutResult = forthSignOutResult = 7;
            firstSignInResult = secondSignInResult = thirdSignInResult = forthSignInResult = 7;
        }
//        boolean signInFlag = (null == monthlyAttendanceIniSignIn || monthlyAttendanceIniSignIn.isEmpty());
//        boolean signOutFlag = (null == monthlyAttendanceIniSignOut || monthlyAttendanceIniSignOut.isEmpty());
        //打卡规则，为什么会有如此的弱智写法 请咨询刘松山
        if (type == 1) {
            secondSignInResult = 0;
            secondSignOutResult = 0;
            thirdSignInResult = 0;
            thirdSignOutResult = 0;
            forthSignInResult = 0;
            forthSignOutResult = 0;
        } else if (type == 2) {
            thirdSignInResult = 0;
            thirdSignOutResult = 0;
            forthSignInResult = 0;
            forthSignOutResult = 0;
        } else if (type == 3) {
            forthSignInResult = 0;
            forthSignOutResult = 0;
        }

        for (int j = 1; j <= type; j++) {
            //打卡时间
            String beginTime = null;
            String endTime = null;
            int endChecked = 0;
            if (j == 1) {
                beginTime = firstBeginTime;
                endTime = firstEndTime;
                endChecked = firstEndChecked;
            }
            if (j == 2) {
                beginTime = secondBeginTime;
                endTime = secondEndTime;
                endChecked = secondEndChecked;
            }
            if (j == 3) {
                beginTime = threeBeginTime;
                endTime = threeEndTime;
                endChecked = threeEndChecked;
            }
            if (j == 4) {
                beginTime = fourBeginTime;
                endTime = fourEndTime;
                endChecked = fourEndChecked;
            }
//            sumOnceAttendance(baseDate, beginTime, endTime, endChecked, j);
            sumOnceAttendance2(baseDate, beginTime, endTime, endChecked, j); // 新增打卡时间
        }
        getNeedSign();
        getAbnormalSign();
        getNormalSign();
    }

    //统计计算方式
    public void sumOnceAttendance(String baseDate, String startTime, String endTime, int endChecked, int attendanceType) {
        //第一次上班打卡时间
        if (StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime)) {
            throw new RuntimeException();
        }
        Date firstBeginAttendanceTime = DateUtils.dateTime(Constant.DATE_FORMAT_1, baseDate.concat(" ").concat(startTime));
        Date firstEndAttendanceTime = (1 == endChecked ? this.calculateDate(baseDate, 1, endTime) : this.calculateDate(baseDate, 0, endTime));
        //----------------fixed 2021-12-02 变更考勤机信息-------------
        //上班时间统计
        if (null != attendanceRecords)
            attendanceDataStatistics(attendanceRecords, firstBeginAttendanceTime, 1, attendanceType);
        //下班时间统计
        if (null != attendanceRecords)
            attendanceDataStatistics(attendanceRecords, firstEndAttendanceTime, 2, attendanceType);
    }

    /**
     * @author: 陈宇寰
     * @date: 2021-12-09 12:39:32
     * @params:
     * @return:
     * @description:
     */
    public void sumOnceAttendance2(String baseDate, String startTime, String endTime, int endChecked, int attendanceType) {
        if (StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime)) {
            throw new RuntimeException();
        }
        //第一次上班打卡时间
        Date firstBeginAttendanceTime = DateUtils.dateTime(Constant.DATE_FORMAT_1, baseDate.concat(" ").concat(startTime));
        Date firstEndAttendanceTime = (1 == endChecked ? this.calculateDate(baseDate, 1, endTime) : this.calculateDate(baseDate, 0, endTime));

        //----------------fixed 2021-12-02 变更考勤机信息-------------
        //上班时间统计
        if (null != attendanceRecords)
            attendanceDataStatistics2(attendanceRecords, firstBeginAttendanceTime, 1, attendanceType);
        //下班时间统计
        if (null != attendanceRecords)
            attendanceDataStatistics2(attendanceRecords, firstEndAttendanceTime, 2, attendanceType);

    }

    /**
     * @param monthlyAttendanceIniSign 考勤数据
     * @param startTime                考勤比较时间
     * @param type                     计算类型 1 上班结果统计 2 下班统计
     * @return void
     * @Description : 统计考勤结果
     * @Author : leizhang
     * @Date 3:52 下午 2021/11/18
     **/
    private void attendanceDataStatistics(List<MonthlyAttendanceIni> monthlyAttendanceIniSign, Date startTime, int type, int attendanceType) {
        long timeDifference = timeDiffer(monthlyAttendanceIniSign, startTime, type);
        if (1 == type) {
            //签到时间小于 60分钟 按旷工处理
            if (timeDifference < -60) {
                //无效打卡
                setSignResult(attendanceType, 7, type);
                abnormalAttendance = 7;
            }
            if (timeDifference > 0) {
                //第一次上班时间统计 根据算法规则获取打卡时间
                /**2-普通迟到 3-一般迟到 4- 严重迟到 5-早退 6-旷工 7-考勤异常 8-休息**/
                if (timeDifference >= termAttendanceRules.getLate() & timeDifference < termAttendanceRules.getGenerallyLate()) {
                    //时差大于迟到时间 小于 一般迟到时间 属于普通迟到
                    setSignResult(attendanceType, 2, type);
                    normallyLate++;
                } else if (timeDifference >= termAttendanceRules.getGenerallyLate() & timeDifference < termAttendanceRules.getSeriouslyLate()) {
                    //时差大于一般迟到到时间 小于 严重迟到时间 属于一般迟到
                    setSignResult(attendanceType, 3, type);
                    usuallyLate++;
                } else if (timeDifference >= termAttendanceRules.getSeriouslyLate() & timeDifference < termAttendanceRules.getAbsenteeism()) {
                    //时差大于严重迟到 小于 旷工的 属于 严重迟到
                    severelyLate++;
                    setSignResult(attendanceType, 4, type);
                } else if (timeDifference >= termAttendanceRules.getAbsenteeism()) {
                    //旷工
                    absenteeism++;
                    setSignResult(attendanceType, 6, type);
                    abnormalAttendance = 2;
                }
            }
        } else {
            //下班打卡时间记录
            if (timeDifference > 60) {
                //超过时间异常，无效打卡
                setSignResult(attendanceType, 7, type);
                abnormalAttendance = 7;
            }
            if (timeDifference < 0) {
                long absValue = 0;
                if ((absValue = Math.abs(timeDifference)) <= termAttendanceRules.getLeaveEarly()) {
                    //时间差在0-早退时间内 早退
                    setSignResult(attendanceType, 5, type);
                    leaveEarly++;
                } else if (absValue > termAttendanceRules.getLeaveEarly()) {
                    //超过早退时间算旷工
                    setSignResult(attendanceType, 6, type);
                    absenteeism++;
                    abnormalAttendance = 2;
                }
            }
        }
    }

    /**
     * @author: 陈宇寰
     * @date: 2021-12-09 11:49:12
     * @params:
     * @return:
     * @description: 新增打卡时间
     */
    private void attendanceDataStatistics2(List<MonthlyAttendanceIni> monthlyAttendanceIniSign, Date startTime, int type, int attendanceType) {
        ImmutableMap timeDifferenceMap = timeDiffer2(monthlyAttendanceIniSign, startTime);
        long timeDifference = (long) timeDifferenceMap.get("timediff");
        Date signTime = (Date) timeDifferenceMap.get("timeval");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm");
        String tempTime = sdf2.format(startTime);
        int inBaseline = -40; // 上班打卡时间允许截止时间
        int outBaseline = 40; // 下班打卡时间允许截止时间
        if (1 == type) {
            if (tempTime.equals(this.firstInTime)) {
                // 早上上班，需要放宽
                inBaseline = -150;
            }
            if (timeDifference < inBaseline || timeDifference > 240) {
                // 早于30分钟打卡不采纳，大于4小时不采纳,视为无效打卡
                setSignResult2(attendanceType, 7, type, null);
                abnormalAttendance = 7;
            } else if (timeDifference <= 0) {
                // 提前半小时以内打卡，正常
                setSignResult2(attendanceType, 1, type, sdf.format(signTime));
            } else {
                //第一次上班时间统计 根据算法规则获取打卡时间
                /**2-普通迟到 3-一般迟到 4- 严重迟到 5-早退 6-旷工 7-考勤异常 8-休息**/
                if (timeDifference <= termAttendanceRules.getLate()) {
                    //时差大于迟到时间 小于 一般迟到时间 属于普通迟到
                    setSignResult2(attendanceType, 2, type, sdf.format(signTime));
                    normallyLate++;
                } else if (timeDifference <= termAttendanceRules.getGenerallyLate()) {
                    //时差大于一般迟到到时间 小于 严重迟到时间 属于一般迟到
                    setSignResult2(attendanceType, 3, type, sdf.format(signTime));
                    usuallyLate++;
                } else if (timeDifference < termAttendanceRules.getSeriouslyLate()) {
                    //时差大于严重迟到 小于 旷工的 属于 严重迟到
                    severelyLate++;
                    setSignResult2(attendanceType, 4, type, sdf.format(signTime));
                } else if (timeDifference >= termAttendanceRules.getAbsenteeism()) {
                    //旷工
                    absenteeism++;
                    setSignResult2(attendanceType, 6, type, sdf.format(signTime));
                    abnormalAttendance = 2;
                }
            }
        } else {
            if (tempTime.equals(this.lastOutTime)) {
                // 下午下班，需要放宽
                outBaseline = 210;
            }
            //下班打卡时间记录
            if (timeDifference > outBaseline || timeDifference < -480) {
                //超过时间异常或者缺失，视为无效打卡
                setSignResult2(attendanceType, 7, type, null);
                abnormalAttendance = 7;
            } else if (timeDifference >= 0) {
                // 正常
                setSignResult2(attendanceType, 1, type, sdf.format(signTime));
            } else {
                // 如果打卡时间小于0，说明提前打卡，提前30分钟以内打卡属于早退，提前30分钟以上打卡属于旷工
                if (Math.abs(timeDifference) <= termAttendanceRules.getLeaveEarly()) {
                    //时间差在0-早退时间内 早退
                    setSignResult2(attendanceType, 5, type, sdf.format(signTime));
                    leaveEarly++;
                } else if (Math.abs(timeDifference) > termAttendanceRules.getLeaveEarly()) {
                    //超过早退时间算旷工
                    setSignResult2(attendanceType, 6, type, timeDifference < -240 ? null : sdf.format(signTime));
                    absenteeism++;
                    abnormalAttendance = 2;
                }
            }
        }
    }

    /**考勤结果值设置，为什么这么写请咨询刘松山打卡规则表是怎么设计的**/
    /**
     * @param attendanceType 第几次打卡
     * @param value          考勤结果
     * @param type           1 上班 2 下班
     * @return void
     * @Description : setSignResult
     * @Author : leizhang
     * @Date 5:27 下午 2021/11/18
     **/
    private void setSignResult(int attendanceType, int value, int type) {
        if (1 == type) {
            switch (attendanceType) {
                case 1:
                    firstSignInResult = value;
                    break;
                case 2:
                    secondSignInResult = value;
                    break;
                case 3:
                    thirdSignInResult = value;
                    break;
                case 4:
                    forthSignInResult = value;
                    break;
                default:
                    break;
            }
        } else if (2 == type) {
            switch (attendanceType) {
                case 1:
                    firstSignOutResult = value;
                    break;
                case 2:
                    secondSignOutResult = value;
                    break;
                case 3:
                    thirdSignOutResult = value;
                    break;
                case 4:
                    forthSignOutResult = value;
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * @author: 陈宇寰
     * @date: 2021-12-09 12:33:47
     * @params:
     * @return:
     * @description:
     */
    private void setSignResult2(int attendanceType, int value, int type, String signTime) {
        if (1 == type) {
            switch (attendanceType) {
                case 1:
                    firstSignInResult = value;
                    firstSignInTime = signTime;
                    break;
                case 2:
                    secondSignInResult = value;
                    secondSignInTime = signTime;
                    break;
                case 3:
                    thirdSignInResult = value;
                    thirdSignInTime = signTime;
                    break;
                case 4:
                    forthSignInResult = value;
                    forthSignInTime = signTime;
                    break;
                default:
                    break;
            }
        } else if (2 == type) {
            switch (attendanceType) {
                case 1:
                    firstSignOutResult = value;
                    firstSignOutTime = signTime;
                    break;
                case 2:
                    secondSignOutResult = value;
                    secondSignOutTime = signTime;
                    break;
                case 3:
                    thirdSignOutResult = value;
                    thirdSignOutTime = signTime;
                    break;
                case 4:
                    forthSignOutResult = value;
                    forthSignOutTime = signTime;
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 获取时间差
     **/
    private long timeDiffer(List<MonthlyAttendanceIni> monthlyAttendanceIniSign, Date startTime, int type) {
        Map<String, MonthlyAttendanceIni> strategyResultBeg = getStrategyResult(monthlyAttendanceIniSign, startTime);
        long timeDifferenceResult = 0;
        if (null == strategyResultBeg.get(Constant.HEAD_VALUE)) {
            timeDifferenceResult = timeDifference(startTime, DateUtils.dateTime(Constant.DATE_FORMAT_1, strategyResultBeg.get(Constant.NEXT_VALUE).getDateTime()));
        } else if (null == strategyResultBeg.get(Constant.NEXT_VALUE)) {
            timeDifferenceResult = timeDifference(startTime, DateUtils.dateTime(Constant.DATE_FORMAT_1, strategyResultBeg.get(Constant.HEAD_VALUE).getDateTime()));
        } else if (null != strategyResultBeg.get(Constant.NEXT_VALUE) && null != strategyResultBeg.get(Constant.NEXT_VALUE)) {
            long timeDifferenceHead = timeDifference(startTime, DateUtils.dateTime(Constant.DATE_FORMAT_1, strategyResultBeg.get(Constant.HEAD_VALUE).getDateTime()));
            long timeDifferenceTail = timeDifference(startTime, DateUtils.dateTime(Constant.DATE_FORMAT_1, strategyResultBeg.get(Constant.NEXT_VALUE).getDateTime()));
            //取绝对值小的数字
            timeDifferenceResult = Math.abs(timeDifferenceHead) > Math.abs(timeDifferenceTail) ? timeDifferenceTail : timeDifferenceHead;
        }
        return timeDifferenceResult;
    }

    /**
     * @author: 陈宇寰
     * @date: 2021-12-09 11:43:20
     * @params:
     * @return:
     * @description:将原来张磊的算法进行了修改，增加了打卡时间的返回
     */
    private ImmutableMap timeDiffer2(List<MonthlyAttendanceIni> monthlyAttendanceIniSign, Date startTime) {
        Map<String, MonthlyAttendanceIni> strategyResultBeg = getStrategyResult(monthlyAttendanceIniSign, startTime);

        ImmutableMap timeDifferenceMap = null;
        if (null == strategyResultBeg.get(Constant.HEAD_VALUE)) {
            timeDifferenceMap = timeDifferenceIncludeDate(startTime, DateUtils.dateTime(Constant.DATE_FORMAT_1, strategyResultBeg.get(Constant.NEXT_VALUE).getDateTime()));
        } else if (null == strategyResultBeg.get(Constant.NEXT_VALUE)) {
            timeDifferenceMap = timeDifferenceIncludeDate(startTime, DateUtils.dateTime(Constant.DATE_FORMAT_1, strategyResultBeg.get(Constant.HEAD_VALUE).getDateTime()));
        } else if (null != strategyResultBeg.get(Constant.NEXT_VALUE) && null != strategyResultBeg.get(Constant.NEXT_VALUE)) {
            ImmutableMap timeDifferenceMap1 = timeDifferenceIncludeDate(startTime, DateUtils.dateTime(Constant.DATE_FORMAT_1, strategyResultBeg.get(Constant.HEAD_VALUE).getDateTime()));
            ImmutableMap timeDifferenceMap2 = timeDifferenceIncludeDate(startTime, DateUtils.dateTime(Constant.DATE_FORMAT_1, strategyResultBeg.get(Constant.NEXT_VALUE).getDateTime()));
            //取绝对值小的数字
            long timeDifferenceHead = (long) timeDifferenceMap1.get("timediff");
            long timeDifferenceTail = (long) timeDifferenceMap2.get("timediff");
            timeDifferenceMap = Math.abs(timeDifferenceHead) > Math.abs(timeDifferenceTail) ? timeDifferenceMap2 : timeDifferenceMap1;
        }
        return timeDifferenceMap;
    }


    /**
     * 计算时间差
     **/
    private long timeDifference(Date startDate, Date endDate) {
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - startDate.getTime();
        // 计算差多少分钟
        return TimeUnit.MILLISECONDS.toMinutes(diff);
    }

    /**
     * @author: 陈宇寰
     * @date: 2021-12-09 11:40:19 陈宇寰改
     * @params: startDate - 规定的打卡时间，endDate - 实际的打卡时间, type - 判断是否是两个端头节点，需要特殊处理
     * @return:
     * @description:
     */
    private ImmutableMap timeDifferenceIncludeDate(Date startDate, Date endDate) {
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - startDate.getTime();
        // 计算差多少分钟
        return ImmutableMap.of("timediff", TimeUnit.MILLISECONDS.toMinutes(diff), "timeval", endDate);
    }

    /**
     * 计算次日日期
     **/
    private Date calculateDate(String baseDate, int amount, String endTime) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtils.dateTime(Constant.DATE_FORMAT_1, baseDate.concat(" ").concat(endTime)));
        calendar.add(Calendar.DATE, amount);
        return calendar.getTime();
    }

    /**
     * @param data
     * @param predictTime {"yyyy-MM-dd HH:mm"}
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @Description : getStrategyResult
     * @Author : leizhang
     * @Date 10:46 上午 2021/10/26
     **/
    public Map<String, MonthlyAttendanceIni> getStrategyResult(List<MonthlyAttendanceIni> data, Date predictTime) {
        int length = data.size();
        MonthlyAttendanceIni headValue = null;
        MonthlyAttendanceIni nextValue = null;
        long predictTimeNumber = predictTime.getTime();
        Map<String, MonthlyAttendanceIni> resultMap = new HashMap<>();
        if (length == 1) {
            //数组为一时 比较前后顺序
            MonthlyAttendanceIni ini = data.get(0);
            long timeNumber = DateUtils.dateTime(Constant.DATE_FORMAT_1, ini.getDateTime()).getTime();
            if (predictTimeNumber < timeNumber) {
                nextValue = ini;
            } else {
                headValue = ini;
            }
        } else {
            for (int i = 0, j = i + 1; i < length; ) {
                long timeNumber = DateUtils.dateTime(Constant.DATE_FORMAT_1, data.get(i).getDateTime()).getTime();
                if (predictTimeNumber <= timeNumber) {
                    nextValue = data.get(i);
                    break;
                }
                long nextTimeNumber = DateUtils.dateTime(Constant.DATE_FORMAT_1, data.get(j).getDateTime()).getTime();
                if (predictTimeNumber >= timeNumber && predictTimeNumber <= nextTimeNumber) {
                    headValue = data.get(i);
                    nextValue = data.get(j);
                    break;
                }
                if (j == length - 1) {
                    headValue = data.get(j);
                    break;
                }
                i++;
                j++;
            }
        }
        resultMap.put(Constant.HEAD_VALUE, headValue);
        resultMap.put(Constant.NEXT_VALUE, nextValue);
        return resultMap;
    }

    public String getIdCard() {
        return idCard;
    }

    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }

    public int getNeedSign() {
        return needSign = type * 2;
    }

    public int getNormalSign() {
        return normalSign = needSign - abnormalSign;
    }

    public int getAbnormalSign() {
        return abnormalSign = normallyLate + usuallyLate + severelyLate + leaveEarly + absenteeism;
    }
}
